home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 18 Cube Mapping / CubeMap / Shaders / LightingUtil.hlsl < prev    next >
Text File  |  2016-03-02  |  6KB  |  171 lines

  1. //***************************************************************************************
  2. // LightingUtil.hlsl by Frank Luna (C) 2015 All Rights Reserved.
  3. //
  4. // Contains API for shader lighting.
  5. //***************************************************************************************
  6.  
  7. #define MaxLights 16
  8.  
  9. struct Light
  10. {
  11.     float3 Strength;
  12.     float FalloffStart; // point/spot light only
  13.     float3 Direction;   // directional/spot light only
  14.     float FalloffEnd;   // point/spot light only
  15.     float3 Position;    // point light only
  16.     float SpotPower;    // spot light only
  17. };
  18.  
  19. struct Material
  20. {
  21.     float4 DiffuseAlbedo;
  22.     float3 FresnelR0;
  23.     float Shininess;
  24. };
  25.  
  26. float CalcAttenuation(float d, float falloffStart, float falloffEnd)
  27. {
  28.     // Linear falloff.
  29.     return saturate((falloffEnd-d) / (falloffEnd - falloffStart));
  30. }
  31.  
  32. // Schlick gives an approximation to Fresnel reflectance (see pg. 233 "Real-Time Rendering 3rd Ed.").
  33. // R0 = ( (n-1)/(n+1) )^2, where n is the index of refraction.
  34. float3 SchlickFresnel(float3 R0, float3 normal, float3 lightVec)
  35. {
  36.     float cosIncidentAngle = saturate(dot(normal, lightVec));
  37.  
  38.     float f0 = 1.0f - cosIncidentAngle;
  39.     float3 reflectPercent = R0 + (1.0f - R0)*(f0*f0*f0*f0*f0);
  40.  
  41.     return reflectPercent;
  42. }
  43.  
  44. float3 BlinnPhong(float3 lightStrength, float3 lightVec, float3 normal, float3 toEye, Material mat)
  45. {
  46.     const float m = mat.Shininess * 256.0f;
  47.     float3 halfVec = normalize(toEye + lightVec);
  48.  
  49.     float roughnessFactor = (m + 8.0f)*pow(max(dot(halfVec, normal), 0.0f), m) / 8.0f;
  50.     float3 fresnelFactor = SchlickFresnel(mat.FresnelR0, halfVec, lightVec);
  51.  
  52.     float3 specAlbedo = fresnelFactor*roughnessFactor;
  53.  
  54.     // Our spec formula goes outside [0,1] range, but we are 
  55.     // doing LDR rendering.  So scale it down a bit.
  56.     specAlbedo = specAlbedo / (specAlbedo + 1.0f);
  57.  
  58.     return (mat.DiffuseAlbedo.rgb + specAlbedo) * lightStrength;
  59. }
  60.  
  61. //---------------------------------------------------------------------------------------
  62. // Evaluates the lighting equation for directional lights.
  63. //---------------------------------------------------------------------------------------
  64. float3 ComputeDirectionalLight(Light L, Material mat, float3 normal, float3 toEye)
  65. {
  66.     // The light vector aims opposite the direction the light rays travel.
  67.     float3 lightVec = -L.Direction;
  68.  
  69.     // Scale light down by Lambert's cosine law.
  70.     float ndotl = max(dot(lightVec, normal), 0.0f);
  71.     float3 lightStrength = L.Strength * ndotl;
  72.  
  73.     return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
  74. }
  75.  
  76. //---------------------------------------------------------------------------------------
  77. // Evaluates the lighting equation for point lights.
  78. //---------------------------------------------------------------------------------------
  79. float3 ComputePointLight(Light L, Material mat, float3 pos, float3 normal, float3 toEye)
  80. {
  81.     // The vector from the surface to the light.
  82.     float3 lightVec = L.Position - pos;
  83.  
  84.     // The distance from surface to light.
  85.     float d = length(lightVec);
  86.  
  87.     // Range test.
  88.     if(d > L.FalloffEnd)
  89.         return 0.0f;
  90.  
  91.     // Normalize the light vector.
  92.     lightVec /= d;
  93.  
  94.     // Scale light down by Lambert's cosine law.
  95.     float ndotl = max(dot(lightVec, normal), 0.0f);
  96.     float3 lightStrength = L.Strength * ndotl;
  97.  
  98.     // Attenuate light by distance.
  99.     float att = CalcAttenuation(d, L.FalloffStart, L.FalloffEnd);
  100.     lightStrength *= att;
  101.  
  102.     return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
  103. }
  104.  
  105. //---------------------------------------------------------------------------------------
  106. // Evaluates the lighting equation for spot lights.
  107. //---------------------------------------------------------------------------------------
  108. float3 ComputeSpotLight(Light L, Material mat, float3 pos, float3 normal, float3 toEye)
  109. {
  110.     // The vector from the surface to the light.
  111.     float3 lightVec = L.Position - pos;
  112.  
  113.     // The distance from surface to light.
  114.     float d = length(lightVec);
  115.  
  116.     // Range test.
  117.     if(d > L.FalloffEnd)
  118.         return 0.0f;
  119.  
  120.     // Normalize the light vector.
  121.     lightVec /= d;
  122.  
  123.     // Scale light down by Lambert's cosine law.
  124.     float ndotl = max(dot(lightVec, normal), 0.0f);
  125.     float3 lightStrength = L.Strength * ndotl;
  126.  
  127.     // Attenuate light by distance.
  128.     float att = CalcAttenuation(d, L.FalloffStart, L.FalloffEnd);
  129.     lightStrength *= att;
  130.  
  131.     // Scale by spotlight
  132.     float spotFactor = pow(max(dot(-lightVec, L.Direction), 0.0f), L.SpotPower);
  133.     lightStrength *= spotFactor;
  134.  
  135.     return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
  136. }
  137.  
  138. float4 ComputeLighting(Light gLights[MaxLights], Material mat,
  139.                        float3 pos, float3 normal, float3 toEye,
  140.                        float3 shadowFactor)
  141. {
  142.     float3 result = 0.0f;
  143.  
  144.     int i = 0;
  145.  
  146. #if (NUM_DIR_LIGHTS > 0)
  147.     for(i = 0; i < NUM_DIR_LIGHTS; ++i)
  148.     {
  149.         result += shadowFactor[i] * ComputeDirectionalLight(gLights[i], mat, normal, toEye);
  150.     }
  151. #endif
  152.  
  153. #if (NUM_POINT_LIGHTS > 0)
  154.     for(i = NUM_DIR_LIGHTS; i < NUM_DIR_LIGHTS+NUM_POINT_LIGHTS; ++i)
  155.     {
  156.         result += ComputePointLight(gLights[i], mat, pos, normal, toEye);
  157.     }
  158. #endif
  159.  
  160. #if (NUM_SPOT_LIGHTS > 0)
  161.     for(i = NUM_DIR_LIGHTS + NUM_POINT_LIGHTS; i < NUM_DIR_LIGHTS + NUM_POINT_LIGHTS + NUM_SPOT_LIGHTS; ++i)
  162.     {
  163.         result += ComputeSpotLight(gLights[i], mat, pos, normal, toEye);
  164.     }
  165. #endif 
  166.  
  167.     return float4(result, 0.0f);
  168. }
  169.  
  170.  
  171.